EST 7030

TL;DR: Enrollment over Secure Transport.

Вступ

Центр сертифікації ключів SYNRC CA/EST

ASN.1 специфікація на модель даних і регламент взаємодії

~/home/synrc/ca/priv/csr/: AlgorithmInformation-2009.asn1 AuthenticationFramework.asn1 BasicAccessControl.asn1 CertificateExtensions.asn1 CryptographicMessageSyntax-2009.asn1 CryptographicMessageSyntaxAlgorithms-2009.asn1 DirectoryAbstractService.asn1 EST.asn1 EnrollmentMessageSyntax-2009.asn1 InformationFramework.asn1 PKCS-10.asn1 PKIX-CommonTypes-2009.asn1 PKIX-X400Address-2009.asn1 PKIX1-PSS-OAEP-Algorithms-2009.asn1 PKIX1Explicit-2009.asn1 PKIX1Implicit-2009.asn1 PKIXAlgs-2009.asn1 SecureMimeMessageV3dot1-2009.asn1 SelectedAttributeTypes.asn1 UpperBounds.asn1 UsefulDefinitions.asn1 ANSI-X9-42.asn1 ANSI-X9-62.asn1 KEP.asn1 DSTU.asn1 OCSP.asn1 LDAP.asn1 CHAT.asn1
EST DEFINITIONS IMPLICIT TAGS ::= BEGIN IMPORTS AttributeSet{}, Extension{}, EXTENSION, ATTRIBUTE FROM PKIX-CommonTypes-2009 CertExtensions FROM PKIX1Implicit-2009 ; Int ::= INTEGER OID ::= OBJECT IDENTIFIER CsrAttrs ::= SEQUENCE OF AttrOrOID AttrOrOID ::= CHOICE { oid OBJECT IDENTIFIER, attribute Attribute } Attribute ::= SEQUENCE { type ATTRIBUTE.&id, values SET SIZE(1..MAX) OF ATTRIBUTE.&Type } Extension ::= SEQUENCE { extnId EXTENSION.&id, critical BOOLEAN DEFAULT FALSE, extnValue EXTENSION.&ExtnType } ExtensionReq ::= SEQUENCE SIZE (1..MAX) OF Extension{{CertExtensions}} at-extension-req ATTRIBUTE ::= { TYPE ExtensionReq IDENTIFIED BY id-ExtensionReq } id-ExtensionReq OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) 14} END

Дерево файлів

~/home/synrc/ca/: ├── openssl/ ├── arvo/ ├── synrc/ ├── config/ ├── include/ ├── lib/ ├── man/ ├── priv/ ├── src/ ├── CNAME ├── LICENSE ├── README.md └── mix.exs
~/home/synrc/ca/lib/: ├── application.ex ├── agreement │   ├── EC │   │   ├── curve.ex │   │   ├── integer.ex │   │   ├── jacobian.ex │   │   └── point.ex │   └── ecc.ex ├── derivation │   ├── hkdf.ex │   └── kdf.ex ├── encryption │   ├── aes.ex │   └── cms.ex ├── oid │   ├── alg.ex │   ├── at.ex │   ├── ce.ex │   ├── kp.ex │   ├── nis.ex │   └── x962.ex ├── services │   ├── cmc.ex │   ├── cmp.ex │   ├── csr.ex │   ├── est.ex │   ├── http │   │   ├── get.ex │   │   └── post.ex │   ├── ocsp.ex │   └── tsp.ex └── signing ├── CAdES.ex ├── ecdsa.ex └── ecdsa_otp.ex

Опис пакету

defmodule CA.Mixfile do use Mix.Project def application(), do: [ mod: {CA, []}, extra_applications: [:x509, :bandit, :plug]] def project() do [ app: :ca, version: "5.10.4", description: "CA CXC 138 21 Certificate Authority", package: [ name: :ca, files: ~w(config src include priv lib mix.exs LICENSE README.md), licenses: ["ISC"], maintainers: ["Namdak Tonpa"], links: %{"GitHub" => "https://github.com/synrc/ca"} ], deps: [ {:jason, "~> 1.2"}, {:plug, "~> 1.15.3"}, {:bandit, "~> 1.0"}, {:ex_doc, ">= 0.0.0", only: :dev}, {:x509, "~> 0.8.7"} ] ] end end

Регламент взаємодії

GET /.well-known/est/ca

def get(conn, [], "Authority", [], "CA") do body = :base64.encode(CA.CSR.read_ca_public()) conn |> put_resp_content_type("application/pkix-cert") |> put_resp_header("Content-Transfer-Encoding", "base64") |> put_resp_header("Content-Length", Integer.to_string(byte_size(body))) |> resp(200, body) |> send_resp() end def read_ca_public() do {:ok, ca_bin} = :file.read_file "ca.pem" {:ok, ca} = X509.Certificate.from_pem ca_bin {:ok, bin} = :"PKIX1Explicit-2009".encode(:Certificate, CA.CMP.convertOTPtoPKIX(ca)) bin end

GET /.well-known/est/cacerts

def get(conn, [], "Authority", [], "CMS") do ca = CA.CSR.read_ca_public() {:ok, cacert} = :"PKIX1Explicit-2009".decode(:Certificate, ca) ci = {:ContentInfo, {1, 2, 840, 113549, 1, 7, 2}, {:SignedData, :v1, [], {:EncapsulatedContentInfo, {1, 2, 840, 113549, 1, 7, 1}, :asn1_NOVALUE}, [certificate: cacert], [], []}} {:ok, cms} = :"CryptographicMessageSyntax-2010".encode :ContentInfo, ci body = :base64.encode cms conn |> put_resp_content_type("application/pkcs7-mime") |> put_resp_header("Content-Transfer-Encoding", "base64") |> put_resp_header("Content-Length", Integer.to_string(byte_size(body))) |> resp(200, body) |> send_resp() end

GET /.well-known/est/csrattrs

def get(conn, [], "Authority", [], "ABAC") do body = :base64.encode(CA.EST.csrattributes()) conn |> put_resp_content_type("application/csrattrs") |> put_resp_header("Content-Transfer-Encoding", "base64") |> put_resp_header("Content-Length", Integer.to_string(byte_size(body))) |> resp(200, body) |> send_resp() end
def csrattributes() do {:ok, bin} = :"EST".encode(:CsrAttrs, [ oid: CA.AT.oid(:"id-at-challengePassword"), oid: CA.X962.oid(:"id-ds-ecdsa-with-SHA384"), attribute: {:Attribute, CA.X962.oid(:"id-kt-ecPublicKey"), [objectIdentifier(CA.ALG.oid(:secp384r1))] }, attribute: {:Attribute, CA.AT.oid(:"id-at-rsaEncryption"), [integer(4096)]}, attribute: {:Attribute, CA.AT.oid(:"id-at-extensionRequest"), [ extension({:Extension, CA.CE.oid(:"id-ce-keyUsage"), true, keyUsage([:digitalSignature, :keyCertSign, :cRLSign])}), extension({:Extension, CA.CE.oid(:"id-ce-basicConstraints"), true, basicConstraints()}), extension({:Extension, CA.CE.oid(:"id-ce-extKeyUsage"), false, extendedKeyUsage([ CA.KP.oid(:"id-kp-serverAuth"), CA.KP.oid(:"id-kp-clientAuth"), CA.KP.oid(:"id-kp-codeSigning"), CA.KP.oid(:"id-kp-emailProtection") ])}) ]} ]) bin end

POST /.well-known/est/simpleenroll

POST /.well-known/est/simplereenroll

POST /.well-known/est/serverkeygen

POST /.well-known/est/fullcmc

Реквізити для ABAC

Додаток 1. Атрибути PKCS-10 CSR запиту

defmodule CA.AT do @moduledoc "CA CSR Attributes OIDs." def oid(:"id-at-rsaEncryption"), do: {1, 2, 840, 113549, 1, 1, 1} def oid(:"id-at-sha1WithRSAEncryption"), do: {1, 2, 840, 113549, 1, 1, 5} def oid(:"id-at-sha512-256WithRSAEncryption"), do: {1, 2, 840, 113549, 1, 1, 16} def oid(:"id-at-dhKeyAgreement"), do: {1, 2, 840, 113549, 1, 3, 1} def oid(:"id-at-emailAddress"), do: {1, 2, 840, 113549, 1, 9, 1} def oid(:"id-at-unstructuredName"), do: {1, 2, 840, 113549, 1, 9, 2} def oid(:"id-at-contentType"), do: {1, 2, 840, 113549, 1, 9, 3} def oid(:"id-at-messageDigest"), do: {1, 2, 840, 113549, 1, 9, 4} def oid(:"id-at-signingTime"), do: {1, 2, 840, 113549, 1, 9, 5} def oid(:"id-at-counterSignature"), do: {1, 2, 840, 113549, 1, 9, 6} def oid(:"id-at-challengePassword"), do: {1, 2, 840, 113549, 1, 9, 7} def oid(:"id-at-unstructuredAddress"), do: {1, 2, 840, 113549, 1, 9, 8} def oid(:"id-at-extendedCertificateAttributes"), do: {1, 2, 840, 113549, 1, 9, 9} def oid(:"id-at-issuerAndSerialNumber"), do: {1, 2, 840, 113549, 1, 9, 10} def oid(:"id-at-passwordCheck"), do: {1, 2, 840, 113549, 1, 9, 11} def oid(:"id-at-publicKey"), do: {1, 2, 840, 113549, 1, 9, 12} def oid(:"id-at-signingDescription"), do: {1, 2, 840, 113549, 1, 9, 13} def oid(:"id-at-extensionRequest"), do: {1, 2, 840, 113549, 1, 9, 14} def oid(:"id-at-smimeCapabilities"), do: {1, 2, 840, 113549, 1, 9, 15}

Додаток 2. Розширення сертифікату

defmodule CA.CE do @moduledoc "CA Certificate Extensions OIDs." def oid(:"id-ce-subjectDirectoryAttributes"), do: {2, 5, 29, 9} def oid(:"id-ce-subjectKeyIdentifier"), do: {2, 5, 29, 14} def oid(:"id-ce-keyUsage"), do: {2, 5, 29, 15} def oid(:"id-ce-privateKeyUsagePeriod"), do: {2, 5, 29, 16} def oid(:"id-ce-subjectAltName"), do: {2, 5, 29, 17} def oid(:"id-ce-issuerAltName"), do: {2, 5, 29, 18} def oid(:"id-ce-basicConstraints"), do: {2, 5, 29, 19} def oid(:"id-ce-cRLNumber"), do: {2, 5, 29, 20} def oid(:"id-ce-reasonCode"), do: {2, 5, 29, 21} def oid(:"id-ce-expirationDate"), do: {2, 5, 29, 22} def oid(:"id-ce-holdInstructionCode"), do: {2, 5, 29, 23} def oid(:"id-ce-invalidityDate"), do: {2, 5, 29, 24} def oid(:"id-ce-deltaCRLIndicator"), do: {2, 5, 29, 27} def oid(:"id-ce-issuingDistributionPoint"), do: {2, 5, 29, 28} def oid(:"id-ce-certificateIssuer"), do: {2, 5, 29, 29} def oid(:"id-ce-nameConstraints"), do: {2, 5, 29, 30} def oid(:"id-ce-cRLDistributionPoints"), do: {2, 5, 29, 31} def oid(:"id-ce-certificatePolicies"), do: {2, 5, 29, 32} def oid(:"id-ce-policyMappings"), do: {2, 5, 29, 33} def oid(:"id-ce-authorityKeyIdentifier"), do: {2, 5, 29, 35} def oid(:"id-ce-policyConstraints"), do: {2, 5, 29, 36} def oid(:"id-ce-extKeyUsage"), do: {2, 5, 29, 37} def oid(:"id-ce-authorityAttributeIdentifier"), do: {2, 5, 29, 38} def oid(:"id-ce-roleSpecCertIdentifier"), do: {2, 5, 29, 39} def oid(:"id-ce-cRLStreamIdentifier"), do: {2, 5, 29, 40} def oid(:"id-ce-basicAttConstraints"), do: {2, 5, 29, 41} def oid(:"id-ce-delegatedNameConstraints"), do: {2, 5, 29, 42} def oid(:"id-ce-timeSpecification"), do: {2, 5, 29, 43} def oid(:"id-ce-crlScope"), do: {2, 5, 29, 44} def oid(:"id-ce-statusReferrals"), do: {2, 5, 29, 45} def oid(:"id-ce-freshestCRL"), do: {2, 5, 29, 46} def oid(:"id-ce-orderedList"), do: {2, 5, 29, 47} def oid(:"id-ce-attributeDescriptor"), do: {2, 5, 29, 48} def oid(:"id-ce-userNotice"), do: {2, 5, 29, 49} def oid(:"id-ce-sOAIdentifier"), do: {2, 5, 29, 50} def oid(:"id-ce-baseUpdateTime"), do: {2, 5, 29, 51} def oid(:"id-ce-acceptableCertPolicies"), do: {2, 5, 29, 52} def oid(:"id-ce-deltaInfo"), do: {2, 5, 29, 53} def oid(:"id-ce-inhibitAnyPolicy"), do: {2, 5, 29, 54} def oid(:"id-ce-targetingInformation"), do: {2, 5, 29, 55} def oid(:"id-ce-noRevAvail"), do: {2, 5, 29, 56} def oid(:"id-ce-acceptablePrivilegePolicies"), do: {2, 5, 29, 57} def oid(:"id-ce-toBeRevoked"), do: {2, 5, 29, 58} def oid(:"id-ce-revokedGroups"), do: {2, 5, 29, 59} def oid(:"id-ce-expiredCertsOnCRL"), do: {2, 5, 29, 60} def oid(:"id-ce-indirectIssuer"), do: {2, 5, 29, 61} def oid(:"id-ce-noAssertion"), do: {2, 5, 29, 62} def oid(:"id-ce-aAissuingDistributionPoint"), do: {2, 5, 29, 63} def oid(:"id-ce-issuedOnBehalfOf"), do: {2, 5, 29, 64} def oid(:"id-ce-singleUse"), do: {2, 5, 29, 65} def oid(:"id-ce-groupAC"), do: {2, 5, 29, 66} def oid(:"id-ce-allowedAttributeAssignments"), do: {2, 5, 29, 67} def oid(:"id-ce-attributeMappings"), do: {2, 5, 29, 68} def oid(:"id-ce-holderNameConstraints"), do: {2, 5, 29, 69} def oid(:"id-ce-authorizationValidation"), do: {2, 5, 29, 70} def oid(:"id-ce-protRestrict"), do: {2, 5, 29, 71} def oid(:"id-ce-subjectAltPublicKeyInfo"), do: {2, 5, 29, 72} def oid(:"id-ce-altSignatureAlgorithm"), do: {2, 5, 29, 73} def oid(:"id-ce-altSignatureValue"), do: {2, 5, 29, 74} def oid(:"id-ce-associatedInformation"), do: {2, 5, 29, 75}

Додаток 3. Призначення ключів сертифікатів

module CA.KP do @moduledoc "CA Key Purpose OIDs." def oid(:"id-kp-serverAuth"), do: {1, 3, 6, 1, 5, 5, 7, 3, 1} def oid(:"id-kp-clientAuth"), do: {1, 3, 6, 1, 5, 5, 7, 3, 2} def oid(:"id-kp-codeSigning"), do: {1, 3, 6, 1, 5, 5, 7, 3, 3} def oid(:"id-kp-emailProtection"), do: {1, 3, 6, 1, 5, 5, 7, 3, 4} def oid(:"id-kp-ipsecEndSystem"), do: {1, 3, 6, 1, 5, 5, 7, 3, 5} def oid(:"id-kp-ipsecTunnel"), do: {1, 3, 6, 1, 5, 5, 7, 3, 6} def oid(:"id-kp-ipsecUser"), do: {1, 3, 6, 1, 5, 5, 7, 3, 7} def oid(:"id-kp-timeStamping"), do: {1, 3, 6, 1, 5, 5, 7, 3, 8} def oid(:"id-kp-OCSPSigning"), do: {1, 3, 6, 1, 5, 5, 7, 3, 9} def oid(:"id-kp-dvcs"), do: {1, 3, 6, 1, 5, 5, 7, 3, 10} def oid(:"id-kp-sbgpCertAAServerAuth"), do: {1, 3, 6, 1, 5, 5, 7, 3, 11} def oid(:"id-kp-scvp-responder"), do: {1, 3, 6, 1, 5, 5, 7, 3, 12} def oid(:"id-kp-eapOverPPP"), do: {1, 3, 6, 1, 5, 5, 7, 3, 13} def oid(:"id-kp-eapOverLAN"), do: {1, 3, 6, 1, 5, 5, 7, 3, 14} def oid(:"id-kp-scvpServer"), do: {1, 3, 6, 1, 5, 5, 7, 3, 15} def oid(:"id-kp-scvpClient"), do: {1, 3, 6, 1, 5, 5, 7, 3, 16} def oid(:"id-kp-ipsecIKE"), do: {1, 3, 6, 1, 5, 5, 7, 3, 17} def oid(:"id-kp-capwapAC"), do: {1, 3, 6, 1, 5, 5, 7, 3, 18} def oid(:"id-kp-capwapWTP"), do: {1, 3, 6, 1, 5, 5, 7, 3, 19} def oid(:"id-kp-sipDomain"), do: {1, 3, 6, 1, 5, 5, 7, 3, 20} def oid(:"id-kp-secureShellClient"), do: {1, 3, 6, 1, 5, 5, 7, 3, 21} def oid(:"id-kp-secureShellServer"), do: {1, 3, 6, 1, 5, 5, 7, 3, 22} def oid(:"id-kp-sendRouter"), do: {1, 3, 6, 1, 5, 5, 7, 3, 23} def oid(:"id-kp-sendProxiedRouter"), do: {1, 3, 6, 1, 5, 5, 7, 3, 24} def oid(:"id-kp-sendOwner"), do: {1, 3, 6, 1, 5, 5, 7, 3, 25} def oid(:"id-kp-sendProxiedOwner"), do: {1, 3, 6, 1, 5, 5, 7, 3, 26} def oid(:"id-kp-cmcCA"), do: {1, 3, 6, 1, 5, 5, 7, 3, 27} def oid(:"id-kp-cmcRA"), do: {1, 3, 6, 1, 5, 5, 7, 3, 28} def oid(:"id-kp-cmcArchive"), do: {1, 3, 6, 1, 5, 5, 7, 3, 29} def oid(:"id-kp-bgpsec-router"), do: {1, 3, 6, 1, 5, 5, 7, 3, 30} def oid(:"id-kp-BrandIndicatorforMessageIdentification"), do: {1, 3, 6, 1, 5, 5, 7, 3, 31} def oid(:"id-kp-cmKGA"), do: {1, 3, 6, 1, 5, 5, 7, 3, 32} def oid(:"id-kp-rpcTLSClient"), do: {1, 3, 6, 1, 5, 5, 7, 3, 33} def oid(:"id-kp-rpcTLSServer"), do: {1, 3, 6, 1, 5, 5, 7, 3, 34} def oid(:"id-kp-bundleSecurity"), do: {1, 3, 6, 1, 5, 5, 7, 3, 35} def oid(:"id-kp-documentSigning"), do: {1, 3, 6, 1, 5, 5, 7, 3, 36} def oid(:"id-kp-jwt"), do: {1, 3, 6, 1, 5, 5, 7, 3, 37} def oid(:"id-kp-httpContentEncrypt"), do: {1, 3, 6, 1, 5, 5, 7, 3, 38} def oid(:"id-kp-oauthAccessTokenSigning"), do: {1, 3, 6, 1, 5, 5, 7, 3, 39} end

˙

[1]. Cisco. PKI: Simplify Certificate Provisioning with EST. 2016
[2]. SYNRC CA/EST Server in Elixir (DHARMA)
[3]. Clarification of RFC7030 CSR Attributes definition
[4]. RFC 7030
[5]. Foundries.io EST Server in Go (BSD-3)